#include "mainwindow.h"
#include "ui_mainwindow.h"



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{

    ui->setupUi(this);
    // Read user-defined IP settings from QSettings
    ipPackReader();
    //Load adapter list here from System
    adapterListMaker();
    // GUI related
    guiMaker();    
    // Systray
    this->mySystemTrayIcon.show();

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}



void MainWindow::on_actionChange_MAC_Address_triggered()
{
    // display mac address changed button!
    if(this->myMB.isHidden())
        this->myMB.show();
    this->myMB.exec();
    //QMessageBox::information(this,"lol", "dgm");
}


void MainWindow::on_comboBox_currentIndexChanged(QString changedAdap)
{
    // Combobox selected item got changed. work here
    this->currentAdapter = changedAdap;
    for (int i = 0; i < this->interfaceList.size(); i++){
        if(this->interfaceList.at(i).name() == changedAdap){
            // Got selected NetworkInterface
            // Get Propertis
            QList<QNetworkAddressEntry> myIPz = this->interfaceList.at(i).addressEntries();
            //QMessageBox::information(this,"Total IP Groups",QString::number(myIPz.length()));
            int selectedGroup = 0;
            QString selectedIP = myIPz.at(selectedGroup).ip().toString();
            QString selectedMask = myIPz.at(selectedGroup).netmask().toString();
            QString selectedGateway = myIPz.at(selectedGroup).broadcast().toString();
            QString selectedMAC = this->interfaceList.at(i).hardwareAddress();
            // put these values in the labels
            ui->label_7->setText(selectedIP);
            ui->label_8->setText(selectedMask);
            ui->label_9->setText(selectedGateway);
            ui->lineEdit_5->setText(selectedMAC);
            // save the index
            this->currentAdapterIndex = i;
            // Update lineEdit Fields from user's previous entry.
            adapterUserSettingsUpdater();
            // do some fun
            this->setWindowOpacity(.95);
            break;
            //QMessageBox::information(this,"lol", changedAdap);
        }
     }
}

void MainWindow::on_commandLinkButton_clicked()
{
    // THE CONNECT BUTTON !!!
    this->populateSubnetMask();
    // SAVE User Input ..  save IPs first
    if(this->currentAdapterIndex != -1){
        QList<QNetworkAddressEntry> myIPz = this->interfaceList.at(this->currentAdapterIndex).addressEntries();
        int selectedGroup = 0; // We forced it to 0. It may be bad...

        // IPZ set successfully. Now start working :P
        // put $current Adapter in the list or update
        int i;
        bool allreadyExist = false;
        for(i=0; i<this->ipList.size(); i++){
            if(this->ipList.at(i).name == this->currentAdapter){
                // Value exists. Update it in the IP-List Vector
                allreadyExist = true;
                this->ipList[i].ip = ui->lineEdit->text();
                this->ipList[i].mask = ui->lineEdit_2->text();
                this->ipList[i].gateway = ui->lineEdit_3->text();
                this->ipList[i].mac = ui->lineEdit_4->text();
                this->ipList[i].isDHCP = (ui->checkBox->isChecked())?(true):(false);
//                QMessageBox::information(this,this->currentAdapter,"You have updated entries for this device.");
                break;
            }
        }
        if(!allreadyExist){
            // Value doesn't exist. add new
            ippack temp(ui->lineEdit->text(), ui->lineEdit_3->text(), ui->lineEdit_2->text(), ui->lineEdit_4->text(), this->currentAdapter);
            temp.isDHCP = (ui->checkBox->isChecked())?(true):(false);
            this->ipList.append(temp);
//            QMessageBox::information(this,this->currentAdapter,"You have created a new device settings.\nYou have modified total: " + QString::number(this->ipList.size()) + " devices.");
        }
        // Okay, save data
        ipPackWriter();
        // Data Saved. Now Hardcore part.... activate settings!
        QString DNS1 = updateDnsFile();
        updateInterfaceFile(DNS1);
        changeMACNow();
    }
}

void MainWindow::ipPackReader(){
    // Reads IPs from QSettings & Store in the list.
    QSettings ipWriter;
    int tempSize = ipWriter.beginReadArray("adapters");
    ippack tempPack;
    this->ipList.clear();
    int i;
    for(i = 0; i< tempSize; i++){
        ipWriter.setArrayIndex(i);
        tempPack.ip = ipWriter.value("ip").toString();
        tempPack.name = ipWriter.value("name").toString();
        tempPack.mask = ipWriter.value("mask").toString();
        tempPack.gateway = ipWriter.value("gateway").toString();
        tempPack.mac = ipWriter.value("mac").toString();
        tempPack.isDHCP = ipWriter.value("isDHCP").toBool();
        this->ipList.append(tempPack);
    }
    ipWriter.endArray();
    ipWriter.sync();
    //QMessageBox::information(this, "IP Read Status", QString::number(i));
}

void MainWindow::ipPackWriter(){
    // writes all Adapters information in settings permanently
    QSettings ipWriter;
    ipWriter.beginWriteArray("adapters");
    for(int i=0; i< this->ipList.size(); i++){
        ipWriter.setArrayIndex(i);
        ipWriter.setValue("ip", this->ipList.at(i).ip);
        ipWriter.setValue("name", this->ipList.at(i).name);
        ipWriter.setValue("mask", this->ipList.at(i).mask);
        ipWriter.setValue("gateway", this->ipList.at(i).gateway);
        ipWriter.setValue("mac", this->ipList.at(i).mac);
        ipWriter.setValue("isDHCP", this->ipList.at(i).isDHCP);
    }
    ipWriter.endArray();
    ipWriter.sync();
    //QMessageBox::information(this,"Success","Settings saved successfully");
}

void MainWindow::adapterListMaker(){
    // Format everything first
    this->myAdapterList.clear();
    ui->comboBox->clear();
    // now load settings
    QNetworkInterface interface;
    this->interfaceList = interface.allInterfaces();
    for (int i = 0; i < this->interfaceList.size(); i++){
        if(this->interfaceList.at(i).name() != "lo" && this->interfaceList.at(i).isValid()){
            if(this->interfaceList.at(i).addressEntries().length() != 0){
                // Entry Validated! Place it in GUI
                this->myAdapterList << this->interfaceList.at(i).name();
            }
        }
     }
    ui->comboBox->addItems(myAdapterList);
}

void MainWindow::adapterUserSettingsUpdater(){
    // Updates GUI lineEdit fields for the selected network Device.
    int i;
    for(i=0; i<this->ipList.size();i++){
        if(this->currentAdapter == this->ipList.at(i).name){
            ui->lineEdit->setText(this->ipList.at(i).ip);
            ui->lineEdit_2->setText(this->ipList.at(i).mask);
            ui->lineEdit_3->setText(this->ipList.at(i).gateway);
            ui->lineEdit_4->setText(this->ipList.at(i).mac);
            (this->ipList.at(i).isDHCP == true)?(ui->checkBox->setChecked(true)):(ui->checkBox->setChecked(false));
            break;
        }
    }
}

QString MainWindow::updateDnsFile(){
    // UPDATES /etc/resolv.conf FILE
    // Fetch DNS Info
    QSettings dnsData;
    QString dns1 = "";
    QString dns2 = "";
    if(dnsData.contains("dns1"))
        dns1 = dnsData.value("dns1").toString();
    if(dnsData.contains("dns2"))
        dns2 = dnsData.value("dns2").toString();
    if(dns1.isEmpty() && dns2.isEmpty())
        return ""; // Nothing to do. User has not updated these files.
    // Update File
    QFile testF("/etc/resolv.conf");
    if(!testF.open(QIODevice::WriteOnly)){
        QString errorM = testF.errorString();
        QMessageBox::critical(this,"DNS Update Failure", "Failed to write necessary files. Be sure to run this application as administrator\nError Details: " + errorM);
        return "";
    }
    QTextStream out(&testF);
    out << "# Generated by MyNetConnector" << endl;
    if(!dns2.isEmpty())
        out << "search " << dns2 << endl;
    if(!dns1.isEmpty())
        out << "nameserver " << dns1 << endl;
    testF.close();
    return dns1;
}

void MainWindow::updateInterfaceFile(QString DNS){
    // Updates /etc/network/interfaces File
    if(this->ipList.size() == 0)
        return; // Nothing to do
    // Open File
    QFile testF("/etc/network/interfaces");
    if(!testF.open(QIODevice::WriteOnly)){
        QString errorM = testF.errorString();
        QMessageBox::critical(this,"IP Update Failure", "Failed to write necessary files. Be sure to run this application as administrator\nError Details: " + errorM);
        return;
    }
    QTextStream out(&testF);
    out << "# Generated by MyNetConnector" << endl;

    for(int i=0; i< this->ipList.size(); i++){
        out << "auto " << this->ipList.at(i).name << endl;
        if(this->ipList.at(i).name == "eth0"){
            out << "allow-hotplug eth0" << endl;
        }
        // perform static/dhcp check and correct here
        if(this->ipList.at(i).isDHCP){
            // DHCP Enabled
            out << "iface " << this->ipList.at(i).name << " inet dhcp" << endl;
        }else{
            // Static Enabled
            out << "iface " << this->ipList.at(i).name << " inet static" << endl;
            if(!this->ipList.at(i).ip.isEmpty())
                out << "address " << this->ipList.at(i).ip << endl;
            if(!this->ipList.at(i).mask.isEmpty())
                out << "netmask " << this->ipList.at(i).mask << endl;
            if(!this->ipList.at(i).gateway.isEmpty())
                out << "gateway " << this->ipList.at(i).gateway << endl;
            if(!DNS.isEmpty())
                out << "dns-nameservers " << DNS << endl;
        }

        out << endl;
    }

    // Generate the Loopback interface settings
    out << "# The loopback network interface" << endl;
    out << "auto lo" << endl;
    out << "iface lo inet loopback" << endl;
}

void MainWindow::changeMACNow(){
    ////////////////////// THE ULTIMATE APPLY SETTINGS BUTTON ////////////////////////////////
    //QObject *parent;
    this->systemTrayMessage("Please wait...","Applying your internet configuration");
    // new window ////////////////////////
    this->hide();
//    if(this->myDialBox.isHidden()){
//        this->myDialBox.show();
//        this->myDialBox.exec();
//    }
    // main works
    QProcess *tempProcess = new QProcess();
    for(int i=0; i<this->ipList.size(); i++){
        if(this->ipList.at(i).mac.isEmpty() || !ui->checkBox_2->isChecked())
            continue;
        tempProcess->start("ifconfig", QStringList() << this->ipList.at(i).name << "down");
        if(!tempProcess->waitForFinished())
            return;
        //QMessageBox::information(this,"status", QString::number(tempProcess->exitStatus()));
        tempProcess->start("ifconfig", QStringList() << this->ipList.at(i).name << "hw" << "ether" << this->ipList.at(i).mac);
        if(!tempProcess->waitForFinished())
            return;
        tempProcess->start("ifconfig", QStringList() << this->ipList.at(i).name << "up");
        if(!tempProcess->waitForFinished())
            return;
        // Update GUI
        ui->lineEdit_5->setText(this->ipList.at(i).mac);
    }
    tempProcess->start("/etc/init.d/networking", QStringList() << "restart");
    if(!tempProcess->waitForFinished())
            return;
    // Okay, all done. bring me live back...
//
//    if(this->myDialBox.isVisible())
//        this->myDialBox.hide();
    this->show();
    //QMessageBox::information(this, "My Network Connector", "Succesfully applied the settings!");
    this->systemTrayMessage("My Net Connector", "Successfully applied the settings!");
    // update the GUI
    this->adapterListMaker();
}

void MainWindow::on_actionDial_up_triggered()
{
    // Execute dial up. First hide myself
    this->hide();
    QProcess *tempProcess = new QProcess();
    tempProcess->start("gnome-terminal", QStringList() << "-e" << "pppoeconf");

    if(!tempProcess->waitForFinished())
        return;
    this->systemTrayMessage("My Net Connector","Returning from dial-up console");
    this->show();
    /*
    dial myDial(this);
    myDial.show();
    myDial.exec();
    */
}

void MainWindow::guiMaker(){
    // set system tray icon
    this->mySystemTrayIcon.setIcon(QIcon(":/icon32"));
    // Validators
    QRegExp rx("^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
    QValidator* ipValidator = new QRegExpValidator( rx, this );

    ui->lineEdit->setValidator(ipValidator);
    ui->lineEdit_2->setValidator(ipValidator);
    ui->lineEdit_3->setValidator(ipValidator);
    // others
    this->setMaximumSize(this->size());
    // set background image
    QPalette pal;
    pal.setBrush( this->backgroundRole(), QBrush( QImage( ":/mncbg" ) ) );
    this->setPalette(pal);

}

void MainWindow::on_actionAbout_triggered()
{
    // About page display
    if(this->aboutWindow.isHidden())
        this->aboutWindow.show();
    this->aboutWindow.exec();
}

bool MainWindow::systemTrayMessage(QString title, QString msg){
    // System Tray message updater
    if(QSystemTrayIcon::isSystemTrayAvailable()){
        if(QSystemTrayIcon::supportsMessages()){
            this->mySystemTrayIcon.showMessage(title,msg);
            return true;
        }
    }
    return false;
}

void MainWindow::systemTrayIconClicked(){
    // a private slot called when system tray icon is clicked.
    QMessageBox::information(this,"oi","icon got clicked");
//    if(this->isVisible())
//        this->hide();
//    else
//        this->show();
}

void MainWindow::on_actionProject_Homepage_triggered()
{
    // Go to project homepage :)
    this->systemTrayMessage("My Network Connector","Project homepage is being opened in your default Web Browser!");
    QDesktopServices::openUrl(QUrl("http://giga.muktosource.com/mnc"));
}

void MainWindow::populateSubnetMask(){
    // If Subnet is not provided, auto calculates it.
    if(ui->lineEdit_2->text().isEmpty() && !ui->lineEdit->text().isEmpty()){
        // Ok, calculate the Subent Mask from IP
        QString user_ip = ui->lineEdit->text();
        QString output_snm = QString::fromStdString(ip2subnetmask::ip2snm(user_ip.toStdString()));
        ui->lineEdit_2->setText(output_snm);
    }
}

void MainWindow::on_actionPing_triggered()
{
    // let user ping an IP
    bool ok;
    QString text = QInputDialog::getText(this, tr("Ping..."),
                                      tr("Enter IP or a domain name:"), QLineEdit::Normal,
                                      "google.com", &ok);
    if (ok && !text.isEmpty()){
        this->hide();
        QProcess *tempProcess = new QProcess();
        QString comnd = "ping -c 4 " + text;
        tempProcess->start("gnome-terminal", QStringList() << "-e" << comnd);
//        tempProcess->write("read getch");
        QString res = tempProcess->readAll();
        if(!tempProcess->waitForFinished())
            return;
        this->show();
        this->systemTrayMessage("My Network Connector", "Pinged " + text);
    }
}

void MainWindow::on_checkBox_stateChanged(int a)
{
    // Checkbox State Changed :)
    if(ui->checkBox->isChecked()){
        ui->lineEdit->setEnabled(false);
        ui->lineEdit_2->setEnabled(false);
        ui->lineEdit_3->setEnabled(false);
    }else{
        ui->lineEdit->setEnabled(true);
        ui->lineEdit_2->setEnabled(true);
        ui->lineEdit_3->setEnabled(true);
    }
}

void MainWindow::on_pushButton_clicked()
{
    // does not exist
}

void MainWindow::on_checkBox_2_clicked()
{
    // Enable MAC checkbox clicked
    if(ui->checkBox_2->isChecked()){
        // Yes, MAC is changable
        ui->lineEdit_4->setEnabled(true);
    }else{
        // No, MAC is not changable
        ui->lineEdit_4->setEnabled(false);
    }
}
